//
//  MobAdNativeView.m
//  kawa_ad
//
//  Created by Payne on 2021/8/4.
//

#import "MobAdNativeView.h"
#import <BUAdSDK/BUAdSDK.h>
#import "KawaAdPlugin.h"

#pragma mark - PlatformView

@interface MobAdNativeView()<FlutterStreamHandler, BUNativeExpressAdViewDelegate>
@property (nonatomic, strong) UIView *containerView;
@property (nonatomic, strong) BUNativeExpressAdView *nativeAd;
@property (nonatomic, strong) BUNativeExpressAdManager *nativeManager;
@property (nonatomic, strong) FlutterResult nativeCallback;

@end

@implementation MobAdNativeView
- (instancetype)initWithFrame:(CGRect)frame
               viewIdentifier:(int64_t)viewId
                    arguments:(id _Nullable)args
                    registrar:(NSObject<FlutterPluginRegistrar> *)registrar
{
    if (self = [super init]) {
        
        // 获取参数
        NSString *unitId;
        CGFloat nativeWidth = 0, nativeHeight = 0;
        if ([args isKindOfClass:[NSDictionary class]]) {
            unitId = args[@"unitId"];
            nativeWidth = [args[@"width"] floatValue];
            nativeHeight = [args[@"height"] floatValue];
        }
        
        if (nativeWidth <= 0.0) {
            nativeWidth = [UIScreen mainScreen].bounds.size.width;
            nativeHeight = 0;
        }
        
        BUAdSlot *slot = [[BUAdSlot alloc] init];
        slot.ID = unitId;
        slot.AdType = BUAdSlotAdTypeFeed;
        BUSize *imageSize = [BUSize sizeBy:BUProposalSize_Feed228_150];
        slot.imgSize = imageSize;
        slot.position = BUAdSlotPositionFeed;
        self.nativeManager = [[BUNativeExpressAdManager alloc] initWithSlot:slot adSize:CGSizeMake(nativeWidth, nativeHeight)];
        self.nativeManager.adSize = CGSizeMake(nativeWidth, nativeHeight);
        self.nativeManager.delegate = self;
        [self.nativeManager loadAdDataWithCount:1];
        // 容器view
        _containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, nativeWidth, nativeHeight)];
        _containerView.backgroundColor = [UIColor clearColor];
        // 事件通道
        NSString *channelName = [NSString stringWithFormat:@"com.mob.adsdk/native_event_%lld", viewId];
        FlutterEventChannel *eventChannel = [FlutterEventChannel eventChannelWithName:channelName binaryMessenger:[registrar messenger]];
        [eventChannel setStreamHandler:self];
    }
    return self;
}

- (void)dealloc {
    NSLog(@"%s", __func__);
}

- (nonnull UIView *)view {
    return _containerView;
}

- (FlutterError* _Nullable)onListenWithArguments:(NSString *_Nullable)arguments
                                       eventSink:(FlutterEventSink)events {
    if (events) {
        self.nativeCallback = events;
    }
    return nil;
}

- (FlutterError *)onCancelWithArguments:(id)arguments {
    return nil;
}

#pragma mark - nativeAdDelegate
/**
 * Sent when views successfully load ad
 */
- (void)nativeExpressAdSuccessToLoad:(BUNativeExpressAdManager *)nativeExpressAdManager views:(NSArray<__kindof BUNativeExpressAdView *> *)views{
    if (views.count > 0) {
        if (self.nativeCallback) {
            self.nativeCallback(@{@"event":@"onAdLoad"});
        }
        self.nativeAd = views[0];
        self.nativeAd.rootViewController = [KawaAdPlugin findCurrentShowingViewController];
        [self.containerView addSubview:self.nativeAd];
        [self.nativeAd render];
        
    }else{
        if (self.nativeCallback) {
            self.nativeCallback(@{@"event":@"onAdError"});
            self.nativeCallback = nil;
        }
    }
}

/**
 * Sent when views fail to load ad
 */
- (void)nativeExpressAdFailToLoad:(BUNativeExpressAdManager *)nativeExpressAdManager error:(NSError *_Nullable)error{
    if (self.nativeCallback) {
        self.nativeCallback(@{@"event":@"onAdError"});
        self.nativeCallback = nil;
    }
}

/**
 * This method is called when a nativeExpressAdView failed to render
 */
- (void)nativeExpressAdViewRenderFail:(BUNativeExpressAdView *)nativeExpressAdView error:(NSError *_Nullable)error{
    if (self.nativeCallback) {
        self.nativeCallback(@{@"event":@"onAdError",@"error":error.localizedDescription,@"code":@(error.code)});
        self.nativeCallback = nil;
    }
}

/**
 * Sent when an ad view is about to present modal content
 */
- (void)nativeExpressAdViewWillShow:(BUNativeExpressAdView *)nativeExpressAdView{
    if (self.nativeCallback) {
        self.nativeCallback(@{@"event":@"onAdShow"});
    }
}

/**
 * Sent when an ad view is clicked
 */
- (void)nativeExpressAdViewDidClick:(BUNativeExpressAdView *)nativeExpressAdView{
    if (self.nativeCallback) {
        self.nativeCallback(@{@"event":@"onAdClick"});
    }
}

/**
Sent when a playerw playback status changed.
@param playerState : player state after changed
*/
- (void)nativeExpressAdView:(BUNativeExpressAdView *)nativeExpressAdView stateDidChanged:(BUPlayerPlayState)playerState{
    if (self.nativeCallback) {
        self.nativeCallback(@{@"event":@"onStateChanged"});
    }
}

/**
 * Sent when a player finished
 * @param error : error of player
 */
- (void)nativeExpressAdViewPlayerDidPlayFinish:(BUNativeExpressAdView *)nativeExpressAdView error:(NSError *)error{
    if (self.nativeCallback) {
        self.nativeCallback(@{@"event":@"onPlayFinish"});
    }
}

/**
 * Sent when a user clicked dislike reasons.
 * @param filterWords : the array of reasons why the user dislikes the ad
 */
- (void)nativeExpressAdView:(BUNativeExpressAdView *)nativeExpressAdView dislikeWithReason:(NSArray<BUDislikeWords *> *)filterWords{
    if (self.nativeCallback) {
        self.nativeCallback(@{@"event":@"onAdClose"});
        [self.nativeAd removeFromSuperview];
    }
}

/**
 * Sent after an ad view is clicked, a ad landscape view will present modal content
 */
- (void)nativeExpressAdViewWillPresentScreen:(BUNativeExpressAdView *)nativeExpressAdView{
    if (self.nativeCallback) {
        self.nativeCallback(@{@"event":@"onAdClickToShow"});
    }
}

/**
 This method is called when another controller has been closed.
 @param interactionType : open appstore in app or open the webpage or view video ad details page.
 */
- (void)nativeExpressAdViewDidCloseOtherController:(BUNativeExpressAdView *)nativeExpressAdView interactionType:(BUInteractionType)interactionType{
    if (self.nativeCallback) {
        self.nativeCallback(@{@"event":@"onAdContentClose"});
    }
}


/**
 This method is called when the Ad view container is forced to be removed.
 @param nativeExpressAdView : Ad view container
 */
- (void)nativeExpressAdViewDidRemoved:(BUNativeExpressAdView *)nativeExpressAdView{
    if (self.nativeCallback) {
        self.nativeCallback(@{@"event":@"onAdClose"});
        [self.nativeAd removeFromSuperview];
    }
}

@end

#pragma mark - PlatformViewFactory

@interface MobAdNativeViewFactory()
@property (nonatomic, strong) NSObject<FlutterPluginRegistrar> *registrar;
@end

@implementation MobAdNativeViewFactory

- (instancetype)initWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
    self = [super init];
    if (self) {
        _registrar = registrar;
    }
    return self;
}

- (NSObject<FlutterMessageCodec>*)createArgsCodec {
    return [FlutterStandardMessageCodec sharedInstance];
}

- (NSObject<FlutterPlatformView> *)createWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id)args {
    return [[MobAdNativeView alloc] initWithFrame:frame viewIdentifier:viewId arguments:args registrar:_registrar];
}

@end
